#region Imports

using System;
using System.Collections.Generic;

#endregion

namespace bGallery.Core.Domain
{
	[Serializable]
	public class Photo 
	{
		#region Private Members

		// State variables
		private bool isChanged;
		private bool isDeleted;

		// Primary Key(s) 
		private int id; 
		
		// Foreign Keys mappate come Many-To-One 
		private Album album; 
		private Phototype phototype; 
		
		// Properties 
		private string filename; 
		private string name; 
		private string abbreviation; 
		private string description; 
		private int size; 
		private int width; 
		private int height; 
		private DateTime inserted; 
		
		// One-to-many relations 
		private IList<Comment> comments;
		private IList<Vote> votes;		

		#endregion
		
		#region Default ( Empty ) Class Constructor
		
		/// <summary>
		/// default constructor
		/// </summary>
		public Photo()
		{
			id = 0; 
			album = null; 
			phototype = null; 
			filename = null; 
			name = null; 
			abbreviation = null; 
			description = null; 
			size = 0; 
			width = 0; 
			height = 0; 
			inserted = DateTime.MinValue; 
			comments = null; 
			votes = null; 
		}
		
		#endregion // End of Default ( Empty ) Class Constructor
		
		#region Full Constructor
		
		/// <summary>
		/// full constructor
		/// </summary>
		public Photo(int id, Album idalbum, Phototype idphototype, string filename, string name, string abbreviation, string description, int size, int width, int height, DateTime inserted)
		{
			this.id = id;
			this.album = idalbum;
			this.phototype = idphototype;
			this.filename = filename;
			this.name = name;
			this.abbreviation = abbreviation;
			this.description = description;
			this.size = size;
			this.width = width;
			this.height = height;
			this.inserted = inserted;
			this.comments = null;
			this.votes = null; 
		}
		
		#endregion // End Full Constructor
		
		#region Required Fields Only Constructor
		
		/// <summary>
		/// required (not null) fields only constructor
		/// </summary>
		public Photo(int id, Album idalbum, Phototype idphototype, string filename, string name, string abbreviation, int size, int width, int height, DateTime inserted)
		{
			this.id = id;
			this.album = idalbum;
			this.phototype = idphototype;
			this.filename = filename;
			this.name = name;
			this.abbreviation = abbreviation;
			this.description = null;
			this.size = size;
			this.width = width;
			this.height = height;
			this.inserted = inserted;
			this.comments = null;
			this.votes = null; 
		}
		
		#endregion // End Required Fields Only Constructor

		#region Public Properties
			
		/// <summary>
		/// Unique identifier
		/// </summary>		
		public virtual int Id
		{
			get { return id; }
			set { isChanged |= (id != value); id = value; }
		} 
	  
		/// <summary>
		/// Album which contains this photo
		/// </summary>		
		public virtual Album Album
		{
			get { return album; }
			set { isChanged |= (album != value); album = value; }
		} 
	  
		/// <summary>
		/// Type of photo
		/// </summary>		
		public virtual Phototype Phototype
		{
			get { return phototype; }
			set { isChanged |= (phototype != value); phototype = value; }
		} 
	  
		/// <summary>
		/// File name of photo on server
		/// </summary>		
		public virtual string Filename
		{
			get { return filename; }
			set	
			{
				if ( value != null )
					if( value.Length > 100)
						throw new ArgumentOutOfRangeException("Invalid value for Filename", value, value.ToString());
				
				isChanged |= (filename != value); filename = value;
			}
		} 
	  
		/// <summary>
		/// Name of the photo
		/// </summary>		
		public virtual string Name
		{
			get { return name; }
			set	
			{
				if ( value != null )
					if( value.Length > 50)
						throw new ArgumentOutOfRangeException("Invalid value for Name", value, value.ToString());
				
				isChanged |= (name != value); name = value;
			}
		} 
	  
		/// <summary>
		/// URL friendly name
		/// </summary>		
		public virtual string Abbreviation
		{
			get { return abbreviation; }
			set	
			{
				if ( value != null )
					if( value.Length > 50)
						throw new ArgumentOutOfRangeException("Invalid value for Abbreviation", value, value.ToString());
				
				isChanged |= (abbreviation != value); abbreviation = value;
			}
		} 
	  
		/// <summary>
		/// Text description of the photo
		/// </summary>		
		public virtual string Description
		{
			get { return description; }
			set	
			{
				if ( value != null )
					if( value.Length > 50)
						throw new ArgumentOutOfRangeException("Invalid value for Description", value, value.ToString());
				
				isChanged |= (description != value); description = value;
			}
		} 
	  
		/// <summary>
		/// Size in bytes
		/// </summary>		
		public virtual int Size
		{
			get { return size; }
			set { isChanged |= (size != value); size = value; }
		} 
	  
		/// <summary>
		/// Photo width in pixels
		/// </summary>		
		public virtual int Width
		{
			get { return width; }
			set { isChanged |= (width != value); width = value; }
		} 
	  
		/// <summary>
		/// Photo height in pixels
		/// </summary>		
		public virtual int Height
		{
			get { return height; }
			set { isChanged |= (height != value); height = value; }
		} 
	  
		/// <summary>
		/// Date when photo was uploaded
		/// </summary>		
		public virtual DateTime Inserted
		{
			get { return inserted; }
			set
			{
				if (inserted == DateTime.MinValue)
				{
					isChanged |= (inserted != value);
					inserted = value;
				}
			}
		} 
	  
		/// <summary>
		/// 
		/// </summary>		
		public virtual IList<Comment> Comments
		{
			get { return comments; }
			set { isChanged |= (comments != value); comments = value; }
		} 
	  
		/// <summary>
		/// 
		/// </summary>		
		public virtual IList<Vote> Votes
		{
			get { return votes; }
			set { isChanged |= (votes != value); votes = value; }
		} 
	  
		/// <summary>
		/// Returns whether or not the object has changed it's values.
		/// </summary>
		public virtual bool IsChanged
		{
			get { return isChanged; }
		}
		
		/// <summary>
		/// Returns whether or not the object has changed it's values.
		/// </summary>
		public virtual bool IsDeleted
		{
			get { return isDeleted; }
		}
		
		#endregion 
		
		#region Public Functions

		/// <summary>
		/// mark the item as deleted
		/// </summary>
		public virtual void MarkAsDeleted()
		{
			isDeleted = true;
			isChanged = true;
		}
		
		#endregion
		
		#region Equals And HashCode Overrides
		
		/// <summary>
		/// local implementation of Equals based on unique value members
		/// </summary>
		public override bool Equals( object obj )
		{
			if( this == obj ) return true;
			if( ( obj == null ) || ( obj.GetType() != this.GetType() ) ) return false;
			Photo castObj = (Photo)obj; 
			return ( castObj != null ) &&
				( this.id == castObj.Id );
		}
		
		/// <summary>
		/// local implementation of GetHashCode based on unique value members
		/// </summary>
		public override int GetHashCode()
		{ 
			int hash = 57; 
			hash = 27 * hash * this.id.GetHashCode();
					
			return hash;		
			
		}
		
		#endregion
		
	}
}